Java JavaScript Python C# C C++ Go Kotlin PHP Swift R Ruby TypeScript Scala SQL Perl rust VisualBasic Matlab Julia

Python Class → Inner Class in Python

Python Class

Inner Class in Python

Inner Classes in Python

Inner classes, also known as nested classes, are classes defined within the scope of another class. They provide a way to logically group related classes and enhance code organization, especially when dealing with complex scenarios. Unlike some languages, Python doesn't strictly enforce a hierarchical relationship between the inner and outer classes; the primary benefit is improved encapsulation and code readability.

Defining Inner Classes

An inner class is simply a class defined within the indentation block of another class. The inner class can access the attributes and methods of its enclosing class (outer class), even private ones (although accessing private attributes of the outer class from an inner class is generally discouraged in favour of proper encapsulation). Example 1: Basic Inner Class
Basic Inner Class in python class OuterClass: outer_attribute = "I'm an outer attribute" def outer_method(self): print("I'm an outer method") class InnerClass: inner_attribute = "I'm an inner attribute" def inner_method(self): print("I'm an inner method") # Accessing inner and outer classes outer_instance = OuterClass() inner_instance = OuterClass.InnerClass() # Inner class is accessed through the outer class print(outer_instance.outer_attribute) outer_instance.outer_method() print(inner_instance.inner_attribute) inner_instance.inner_method() #Accessing Outer class from Inner class inner_instance2 = OuterClass().InnerClass() class OuterClass2: def __init__(self, val): self.val = val self.inner = self.InnerClass() class InnerClass: def show_outer(self): # Accessing outer class attribute using outer instance print(f"outer value: {self.outer.val}") outer_instance3 = OuterClass2(100) #outer_instance3.inner.show_outer() # Error if inner class doesn't have a link to the outer class #The above error shows that to access outer class properties we need a refrence.

Output

I'm an outer attribute I'm an outer method I'm an inner attribute I'm an inner method

Example 2: Inner Class with Access to Outer Class Attributes and Methods
Inner Class with Access to Outer Class Attributes and Methods class BankAccount: def __init__(self, account_number, balance): self.account_number = account_number self._balance = balance # Using a protected attribute def get_balance(self): return self._balance class Transaction: def __init__(self, amount, description, account): self.amount = amount self.description = description self.account = account # Reference to the outer BankAccount instance def process(self): if self.amount > 0: self.account._balance += self.amount print(f"Deposit of {self.amount} processed.") else: if abs(self.amount) <= self.account._balance: self.account._balance += self.amount print(f"Withdrawal of {abs(self.amount)} processed.") else: print("Insufficient funds.") account = BankAccount("12345", 1000) transaction = BankAccount.Transaction(500, "Deposit", account) transaction.process() print(account.get_balance()) transaction2 = BankAccount.Transaction(-200, "Withdrawal", account) transaction2.process() print(account.get_balance()) transaction3 = BankAccount.Transaction(-1500, "Withdrawal", account) transaction3.process()

Output

Deposit of 500 processed. 1500 Withdrawal of 200 processed. 1300 Insufficient funds.
In this example, the `Transaction` inner class is tightly coupled with `BankAccount`. It needs a `BankAccount` instance to function. The inner class accesses the `_balance` attribute (although accessing protected attributes of the outer class directly from the inner class is generally discouraged, in this case it helps show that we can access them if we wish to).
Example 3: Enclosing Instance as an Argument (Best Practice) This method is preferred to avoid accidental access of the Outer Class without a valid instance
Enclosing Instance as an Argument - python innner class example class MyClass: def __init__(self,value): self.value = value class InnerClass: def __init__(self,outer): self.outer = outer def print_outer(self): print(f"Outer class value is {self.outer.value}") outer_class_instance = MyClass(10) inner_class_instance = MyClass.InnerClass(outer_class_instance) inner_class_instance.print_outer()

Output

Outer class value is 1

When to Use Inner Classes

Logical Grouping: When a class is intrinsically related to another and doesn't make sense outside of its context. Encapsulation: To hide the inner class's implementation details from the outside world, improving maintainability. Avoiding Namespace Pollution: Prevents naming conflicts by nesting classes within a specific scope. Helper Classes: Inner classes can act as helper classes that are only relevant to the functionality of the outer class.

Important Considerations

Access to Outer Class Members: Inner classes have direct access to the members (attributes and methods) of their enclosing class. Instantiation: You need an instance of the outer class to create an instance of an inner class (unless the inner class is declared as static/class method) . Naming Conventions: Use clear and descriptive names to improve code readability.

Tutorials